package me.zhengjie.sysrunner;

import me.zhengjie.gas.dto.CodeFirstMigrationDto;
import me.zhengjie.gas.repositories.CodeFirstMigrationRepository;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

@Component
public class MigrationRnner implements InitializingBean {
	@Autowired
	private DataSource dataSource;

	@Autowired
	private CodeFirstMigrationRepository codeFirstMigrationRepository;

	private void executeMigrationScripts() throws IOException, SQLException {
		String remarks = "normal_script";
		Boolean isNeedToSave = true;
		Boolean isDefaultScript = true;

		System.out.println("run migration 12345:");

		List<CodeFirstMigrationDto> codeFirstMigrationList = codeFirstMigrationRepository.findCodeFirstMigrationList();
		ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
		Resource[] resources = resourcePatternResolver.getResources("classpath:migration/*.sql");

		try (Connection connection = dataSource.getConnection()) {
			for (Resource resource : resources) {
				String fileName = resource.getFilename();
				System.out.println("File name: " + fileName);
				boolean isDbFileNameFound = codeFirstMigrationList.stream()
						.anyMatch(migration -> migration.getFileName().equals(fileName) && !migration.getIsDefaultScript() && migration.getRemarks().equals(remarks));
				if (!isDbFileNameFound) {
					executeScript(connection, resource, isNeedToSave, isDefaultScript, remarks);
				}
			}
		}
	}

	private void executeScript(Connection connection, Resource resource, Boolean isNeedToSave, Boolean isDefaultScript, String remarks) throws IOException {
		String fileName = resource.getFilename();
		Boolean isSuccess = null;
		String message = null;

		try (Statement statement = connection.createStatement();
		     BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8))) {
			StringBuilder script = new StringBuilder();
			String line;
			while ((line = reader.readLine()) != null) {
				script.append(line);
				script.append("\n"); // Append a newline character after each line
			}
			statement.execute(script.toString());
			isSuccess = true;
		} catch (SQLException e) {
			isSuccess = false;
			message = e.getMessage();
			System.out.println("Migration error: " + message);
			throw new RuntimeException(e);
		} finally {
			if (isNeedToSave) {
				CodeFirstMigrationDto codeFirstMigration = new CodeFirstMigrationDto();
				codeFirstMigration.setFileName(fileName);
				codeFirstMigration.setIsProcessed(true);
				codeFirstMigration.setIsSuccess(isSuccess);
				codeFirstMigration.setErrorLogMessage(message);
				codeFirstMigration.setIsDefaultScript(isDefaultScript);
				codeFirstMigration.setRemarks(remarks);
				codeFirstMigrationRepository.save(codeFirstMigration);
			}
		}
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		executeMigrationScripts();
	}
}
